# ----------------------------------------------------------------------------
#       Copyright (C) 2013-2014 Huynh Vi Lam  <domovilam@gmail.com>
#
#       This file is part of pimucha.
#
#	This program is free software: you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation, either version 3 of the License, or
#	(at your option) any later version.
#	
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#	
#	You should have received a copy of the GNU General Public License
#	along with this program.  If not, see <http://www.gnu.org/licenses/>.
# ----------------------------------------------------------------------------



# ----------------------------------------------------------------------------
# Script for devices and controllers
# with USB interface
# Require python-usb >= 1.0
# Python version 2.7.x and 3.x
# ----------------------------------------------------------------------------
# pyUSB
# -----
# - Website: https://github.com/walac/pyusb
# - Documentation and source code pyUSB is used as base for development
# ----------------------------------------------------------------------------


import logging,time,sys
import usb.core, usb.util
from piHAlibs import confgetval

logger = logging.getLogger()


def vidpid(vid):
    try:
        p = vid.split(':')
        return int(p[0],16), int(p[1],16)
    except:
        return None,None

def usbport(port):
    try:
        p = port.split(':')
        if port.startswith('0x'):
            return int(p[0],16),int(p[1],16)
        else:
            return int(p[0]),int(p[1])
    except:
        return None,None

def finddevId(devId):
    vendorId = None
    productId = None
    if devId:
        vendorId, productId = vidpid(devId)
    backend = findbackend()
    usbdevs = None
    try:
        logger.debug("Finding USB device with Id %s....",devId)
        if backend:
            usbdevs = usb.core.find(find_all=True, idVendor=vendorId, idProduct=productId, backend=backend)
        else:
            usbdevs = usb.core.find(find_all=True, idVendor=vendorId, idProduct=productId)
    except Exception as e:
        logger.critical("%s : %s", repr(e.__class__), str(e))
        if 'No backend available' in str(e) and backend is not None:
            print ('You may supply path to libusb in pimucha.conf, and retry')
    return usbdevs

def findbackend():
    # usblib1 = /usr/lib/libusb-1.0.so
    # No backend available
    usblib1 = confgetval('pimucha.conf','libUSB','usblib1',None)
    if usblib1:
        import usb.backend.libusb1
        return usb.backend.libusb1.get_backend(find_library=lambda x: usblib1)
    usblib0 = confgetval('pimucha.conf','libUSB','usblib0',None)
    if usblib0:
        import usb.backend.libusb0
        return usb.backend.libusb0.get_backend(find_library=lambda x: usblib0)

def findbusadd(port):
    b = 0
    a = 0
    if port:
        b, a = usbport(port)
    usbdev = None
    try:
        logger.debug("Finding USB in port %s....",port)
        usbdev = usb.core.find(bus=b, address=a)
    except Exception as e:
        logger.critical("%s : %s", repr(e.__class__), str(e))
    return usbdev

def finddevice(devId,port=None):
    usbdevs = finddevId(devId)
    if usbdevs:
        nbdev = len(usbdevs)
        bus, addr = usbport(port)
    else:
        nbdev = 0
    if nbdev > 1:
        logger.warning("Found %s USB device(s) : %s",str(nbdev),repr(usbdevs))
        for dev in usbdevs:
            if (dev.bus == bus) and (dev.address == addr):
                return dev
            else:
                logger.debug("USB found at bus %s and address %s", ("%03d" % dev.bus), ("%03d" % dev.address))
        else:           
            logger.error("A choice is needed for USB device")
            return None
    elif nbdev == 1:
        return usbdevs[0]
    else:
        return None
